home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume12 / cake / part04 < prev    next >
Encoding:
Internet Message Format  |  1987-10-14  |  30.2 KB

  1. Subject:  v12i010:  Cake, a make replacement, Part04/09
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: Zoltan Somogyi <zs@munnari.oz>
  7. Posting-number: Volume 12, Issue 10
  8. Archive-name: cake/part04
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create:
  15. #    README
  16. #    Makefile
  17. #    base.c
  18. #    ccincl.c
  19. #    ccincl_s.l
  20. #    gsrc.c
  21. #    later.c
  22. #    need.c
  23. #    needed.c
  24. #    pattern_s.l
  25. #    refs.c
  26. #    std.h
  27. #    sub.c
  28. #    subcmd.c
  29. #    usrc.c
  30. # This archive created: Wed Oct 14 20:49:51 1987
  31. export PATH; PATH=/bin:/usr/bin:$PATH
  32. echo mkdir Aux
  33. mkdir Aux
  34. echo cd Aux
  35. cd Aux
  36. echo shar: "extracting 'README'" '(172 characters)'
  37. if test -f 'README'
  38. then
  39.     echo shar: "will not over-write existing file 'README'"
  40. else
  41. sed 's/^X//' << \SHAR_EOF > 'README'
  42. XThis directory contains the sources for commands used by some
  43. X"standard" cakefiles. You shouldn't need to do more than modify
  44. XDEST in the Makefile and type "make install".
  45. SHAR_EOF
  46. if test 172 -ne "`wc -c < 'README'`"
  47. then
  48.     echo shar: "error transmitting 'README'" '(should have been 172 characters)'
  49. fi
  50. fi
  51. echo shar: "extracting 'Makefile'" '(836 characters)'
  52. if test -f 'Makefile'
  53. then
  54.     echo shar: "will not over-write existing file 'Makefile'"
  55. else
  56. sed 's/^X//' << \SHAR_EOF > 'Makefile'
  57. X#    Makefile for some of cake's auxiliary programs
  58. X
  59. XPROGS = base ccincl later need needed sub subcmd usrc gsrc
  60. XDEST  = /mip/usr/bin
  61. X
  62. Xall:        $(PROGS)
  63. X
  64. Xinstall:    $(PROGS)
  65. X        cp $(PROGS) $(DEST)
  66. X
  67. Xbase:        base.o pattern_s.o
  68. X        cc -o base base.o pattern_s.o
  69. X
  70. Xccincl:        ccincl.o ccincl_s.o
  71. X        cc -o ccincl ccincl.o ccincl_s.o
  72. X
  73. Xlater:        later.c
  74. X        cc -o later later.c
  75. X
  76. Xneed:        need.c
  77. X        cc -o need need.c
  78. X
  79. Xneeded:        needed.c
  80. X        cc -o needed needed.c
  81. X
  82. Xrefs:        refs.o pattern_s.o
  83. X        cc -o refs refs.o pattern_s.o
  84. X
  85. Xsub:        sub.c
  86. X        cc -o sub sub.c
  87. X
  88. Xsubcmd:        subcmd.c
  89. X        cc -o subcmd subcmd.c
  90. X
  91. Xusrc:        usrc.c
  92. X        cc -o usrc usrc.c
  93. X
  94. Xgsrc:        gsrc.c
  95. X        cc -o gsrc gsrc.c
  96. X
  97. Xccincl_s.c:    ccincl_s.l
  98. X        lex ccincl_s.l
  99. X        @mv lex.yy.c ccincl_s.c
  100. X
  101. Xpattern_s.c:    pattern_s.l
  102. X        lex pattern_s.l
  103. X        @mv lex.yy.c pattern_s.c
  104. X
  105. Xclean:        
  106. X        /bin/rm    Make_errs *.o *_s.c
  107. X
  108. Xgclean:        
  109. X        /bin/rm *_s.c
  110. SHAR_EOF
  111. if test 836 -ne "`wc -c < 'Makefile'`"
  112. then
  113.     echo shar: "error transmitting 'Makefile'" '(should have been 836 characters)'
  114. fi
  115. fi
  116. echo shar: "extracting 'base.c'" '(754 characters)'
  117. if test -f 'base.c'
  118. then
  119.     echo shar: "will not over-write existing file 'base.c'"
  120. else
  121. sed 's/^X//' << \SHAR_EOF > 'base.c'
  122. X/*
  123. X**    A program to prepare a base for spell and style
  124. X*/
  125. X
  126. X#include    <stdio.h>
  127. X#include    "std.h"
  128. X
  129. Xtypedef    struct    s_entry
  130. X{
  131. X    bool    reflexive;
  132. X    char    *replacement;
  133. X} Entry;
  134. X
  135. XEntry    table[5] =    /* we use subscripts 1 to 4 */
  136. X{
  137. X    {    FALSE,    ""        },
  138. X    {    TRUE,    "EQUATION"    },
  139. X    {    FALSE,    "(REFERENCE)"    },
  140. X    {    FALSE,    "PROGRAM"    },
  141. X    {    FALSE,    "PICTURE"    },
  142. X};
  143. X
  144. Xint    more = TRUE;
  145. X
  146. Xmain()
  147. X{
  148. X    extern    char    yytext[];
  149. X    reg    int    code;
  150. X
  151. X    code = yylex();
  152. X    while (more)
  153. X    {
  154. X        if (code <= 0)
  155. X            fputs(yytext, stdout);
  156. X        else
  157. X        {
  158. X            reg    int    oldcode;
  159. X            reg    int    newcode;
  160. X
  161. X            oldcode = code;
  162. X            newcode = table[code].reflexive? code: -code;
  163. X
  164. X            code = yylex();
  165. X            while (more && code != newcode)
  166. X                code = yylex();
  167. X            
  168. X            printf(table[oldcode].replacement);
  169. X        }
  170. X
  171. X        code = yylex();
  172. X    }
  173. X
  174. X    exit(0);
  175. X}
  176. SHAR_EOF
  177. if test 754 -ne "`wc -c < 'base.c'`"
  178. then
  179.     echo shar: "error transmitting 'base.c'" '(should have been 754 characters)'
  180. fi
  181. fi
  182. echo shar: "extracting 'ccincl.c'" '(5068 characters)'
  183. if test -f 'ccincl.c'
  184. then
  185.     echo shar: "will not over-write existing file 'ccincl.c'"
  186. else
  187. sed 's/^X//' << \SHAR_EOF > 'ccincl.c'
  188. X/*
  189. X**    Ccincl main file.
  190. X*/
  191. X
  192. Xstatic    char
  193. Xrcs_id[] = "$Header$";
  194. X
  195. X#include    <ctype.h>
  196. X#include    <stdio.h>
  197. X#include    <sys/types.h>
  198. X#include    <sys/stat.h>
  199. X#include    "std.h"
  200. X
  201. Xtypedef    struct    stat    Stat;
  202. X
  203. X#define    MAXDIRS        10
  204. X#define    MAXSTOPS    10
  205. X#define    MAXIGNORES    10
  206. X#define    MAXFILES    64
  207. X#define    MAXBUF        512
  208. X
  209. Xchar    *dir_list[MAXDIRS];
  210. Xchar    *stop_list[MAXSTOPS];
  211. Xchar    *ign_list[MAXIGNORES];
  212. Xchar    *file_list[MAXFILES];
  213. Xbool    search_list[MAXFILES];
  214. Xino_t    ino_list[MAXFILES];
  215. Xint    dircount = 0;
  216. Xint    stopcount = 0;
  217. Xint    igncount = 0;
  218. Xint    filecount = 0;
  219. X
  220. Xchar    *currdir = ".";
  221. Xchar    *filename;
  222. XStat    statbuf;
  223. Xint    rflag = FALSE;
  224. Xint    fflag = FALSE;
  225. Xint    errorcount = 0;
  226. X
  227. Xmain(argc, argv)
  228. Xint    argc;
  229. Xchar    **argv;
  230. X{
  231. X    extern    FILE    *yyin;
  232. X    reg    int    i;
  233. X
  234. X    dir_list[dircount++] = ".";
  235. X    while (argc > 1 && argv[1][0] == '-')
  236. X    {
  237. X        for (i = 1; argv[1][i] != '\0'; i++)
  238. X        {
  239. X            switch (argv[1][i])
  240. X            {
  241. X
  242. X        when 'f':
  243. X                fflag = TRUE;
  244. X        when 'r':
  245. X                rflag = TRUE;
  246. X        when 'i':
  247. X                if (i != 1)
  248. X                    usage();
  249. X
  250. X                ign_list[igncount++] = &argv[1][2];
  251. X                file_list[filecount] = &argv[1][2];
  252. X
  253. X                if (stat(&argv[1][2], &statbuf) != 0)
  254. X                {
  255. X                    printf("ccincl: cannot find %s\n", &argv[1][2]);
  256. X                    exit(1);
  257. X                }
  258. X
  259. X                search_list[filecount] = FALSE;
  260. X                ino_list[filecount] = statbuf.st_ino;
  261. X                filecount++;
  262. X                goto nextword;
  263. X        when 's':
  264. X                if (i != 1)
  265. X                    usage();
  266. X
  267. X                stop_list[stopcount++] = &argv[1][2];
  268. X                file_list[filecount] = &argv[1][2];
  269. X
  270. X                if (stat(&argv[1][2], &statbuf) != 0)
  271. X                {
  272. X                    printf("ccincl: cannot find %s\n", &argv[1][2]);
  273. X                    exit(1);
  274. X                }
  275. X
  276. X                search_list[filecount] = FALSE;
  277. X                ino_list[filecount] = statbuf.st_ino;
  278. X                filecount++;
  279. X                goto nextword;
  280. X        when 'C':
  281. X                if (i != 1)
  282. X                    usage();
  283. X
  284. X                currdir = &argv[1][2];
  285. X                goto nextword;
  286. X        when 'I':
  287. X                if (i != 1)
  288. X                    usage();
  289. X
  290. X                dir_list[dircount++] = &argv[1][2];
  291. X                goto nextword;
  292. X        otherwise:
  293. X                usage();
  294. X            }
  295. X        }
  296. X
  297. Xnextword:
  298. X        argc--;
  299. X        argv++;
  300. X    }
  301. X
  302. X    dir_list[dircount++] = "/usr/include";
  303. X    if (dircount > MAXDIRS)
  304. X    {
  305. X        printf("ccincl: too many dir_list.\n");
  306. X        exit(1);
  307. X    }
  308. X
  309. X    if (argc < 2)
  310. X        usage();
  311. X    
  312. X    while (argc > 1)
  313. X    {
  314. X        file_list[filecount] = argv[1];
  315. X        if (stat(argv[1], &statbuf) != 0)
  316. X        {
  317. X            printf("ccincl: cannot find %s\n", argv[1]);
  318. X            exit(1);
  319. X        }
  320. X
  321. X        search_list[filecount] = TRUE;
  322. X        ino_list[filecount] = statbuf.st_ino;
  323. X        filecount++;
  324. X        argc--;
  325. X        argv++;
  326. X    }
  327. X    
  328. X    for (i = 0; i < filecount; i++)
  329. X    {
  330. X        if (! search_list[i])
  331. X            continue;
  332. X
  333. X        filename = file_list[i];
  334. X        if ((yyin = fopen(filename, "r")) == NULL)
  335. X        {
  336. X            fflush(stdout);
  337. X            perror("ccincl");
  338. X            printf("ccincl: cannot open %s\n", filename);
  339. X            exit(1);
  340. X        }
  341. X
  342. X        yylex();
  343. X        fclose(yyin);
  344. X    }
  345. X
  346. X    exit(errorcount);
  347. X}
  348. X
  349. Xprocess(line)
  350. Xreg    char    *line;
  351. X{
  352. X    extern    char    *malloc();
  353. X    extern    int    yylineno;
  354. X    char        buf[MAXBUF];
  355. X    reg    char    *s, *start;
  356. X    reg    int    i, startdir;
  357. X    reg    bool    index;
  358. X    reg    char    endchar;
  359. X    reg    bool    found;
  360. X
  361. X    for (s = line+1; *s != '\0' && isspace(*s); s++)
  362. X        ;
  363. X    
  364. X    if (strndiff(s, "include", 7))
  365. X        return;
  366. X    
  367. X    for (s += 7; *s != '\0' && isspace(*s); s++)
  368. X        ;
  369. X    
  370. X    if (*s == '<')
  371. X        endchar = '>', startdir = 1;
  372. X    else
  373. X        endchar = '"', startdir = 0;
  374. X
  375. X    start = s+1;
  376. X    for (s = start; *s != '\0' && *s != endchar; s++)
  377. X        ;
  378. X
  379. X    if (*s != endchar)
  380. X    {
  381. X        printf("ccincl: %s(%d) bad include syntax\n", filename, yylineno);
  382. X        errorcount++;
  383. X        return;
  384. X    }
  385. X
  386. X    /* terminate arg (now pointed to by start) */
  387. X    *s = '\0';
  388. X
  389. X    /* handle absolute pathnames */
  390. X    if (*start == '/')
  391. X    {
  392. X        sprintf(buf, "%s", start);
  393. X        goto end;
  394. X    }
  395. X
  396. X    /* handle relative pathnames */
  397. X    if (*start == '.')
  398. X    {
  399. X        sprintf(buf, "%s/%s", currdir, start);
  400. X        goto end;
  401. X    }
  402. X
  403. X    /* handle implicit pathnames */
  404. X    found = FALSE;
  405. X    for (i = startdir; i < dircount; i++)
  406. X    {
  407. X        if (i == 0)
  408. X        {
  409. X            if (streq(currdir, "."))
  410. X                strcpy(buf, "");
  411. X            else
  412. X            {
  413. X                strcpy(buf, dir_list[i]);
  414. X                strcat(buf, "/");
  415. X            }
  416. X
  417. X            strcat(buf, start);
  418. X        }
  419. X        else
  420. X        {
  421. X            strcpy(buf, dir_list[i]);
  422. X            strcat(buf, "/");
  423. X            strcat(buf, start);
  424. X        }
  425. X
  426. X        if (strlen(buf) > MAXBUF)
  427. X        {
  428. X            printf("ccincl: buffer length exceeded\n");
  429. X            exit(1);
  430. X        }
  431. X
  432. X        if (stat(buf, &statbuf) == 0)
  433. X        {
  434. X            found = TRUE;
  435. X            break;
  436. X        }
  437. X    }
  438. X
  439. X    if (! found)
  440. X    {
  441. X        printf("ccincl: cannot find %s\n", start);
  442. X        errorcount++;
  443. X        return;
  444. X    }
  445. X
  446. Xend:
  447. X    if (stat(buf, &statbuf) != 0)
  448. X    {
  449. X        printf("ccincl: cannot stat %s\n", buf);
  450. X        errorcount++;
  451. X        return;
  452. X    }
  453. X
  454. X    found = FALSE;
  455. X    for (i = 0; i < filecount; i++)
  456. X        if (ino_list[i] == statbuf.st_ino)
  457. X        {
  458. X            found = TRUE;
  459. X            index = i;
  460. X            break;
  461. X        }
  462. X
  463. X    if (! found)
  464. X    {
  465. X        index = filecount;
  466. X        ino_list[filecount]    = statbuf.st_ino;
  467. X        search_list[filecount] = FALSE;
  468. X        file_list[filecount]   = malloc(strlen(buf)+1);
  469. X        strcpy(file_list[filecount], buf);
  470. X        filecount++;
  471. X    }
  472. X
  473. X    for (i = 0; i < igncount; i++)
  474. X        if (streq(file_list[index], ign_list[i]))
  475. X            return;
  476. X
  477. X    if (fflag)
  478. X        printf("%s: ", filename);
  479. X
  480. X    printf("%s\n", file_list[index]);
  481. X
  482. X    if (rflag)
  483. X    {
  484. X        for (i = 0; i < stopcount; i++)
  485. X            if (streq(buf, stop_list[i]))
  486. X                return;
  487. X
  488. X        search_list[filecount] = TRUE;
  489. X    }
  490. X}
  491. X
  492. X/*
  493. X**    Tell the unfortunate user how to use ccincl.
  494. X*/
  495. X
  496. Xusage()
  497. X{
  498. X    printf("Usage: ccincl [-rf] [-ifile] [-sfile] [-Cdir] [-Idir] ... file ...\n");
  499. X    exit(1);
  500. X}
  501. SHAR_EOF
  502. if test 5068 -ne "`wc -c < 'ccincl.c'`"
  503. then
  504.     echo shar: "error transmitting 'ccincl.c'" '(should have been 5068 characters)'
  505. fi
  506. fi
  507. echo shar: "extracting 'ccincl_s.l'" '(240 characters)'
  508. if test -f 'ccincl_s.l'
  509. then
  510.     echo shar: "will not over-write existing file 'ccincl_s.l'"
  511. else
  512. sed 's/^X//' << \SHAR_EOF > 'ccincl_s.l'
  513. X%{
  514. X/*
  515. X**    Scanner for ccincl
  516. X*/
  517. X
  518. Xstatic    char
  519. Xrcs_id[] = "$Header$";
  520. X
  521. X#undef    YYLMAX
  522. X#define    YYLMAX    512
  523. X%}
  524. X
  525. Xnl    [\n\f]
  526. Xnonl    [^\n\f]
  527. X
  528. X%%
  529. X
  530. X#{nonl}*{nl}        {
  531. X                process(yytext);
  532. X                fflush(stdout);
  533. X            }
  534. X
  535. X{nonl}*{nl}        ;
  536. X
  537. X%%
  538. X
  539. Xyywrap()
  540. X{
  541. X    return 1;
  542. X}
  543. SHAR_EOF
  544. if test 240 -ne "`wc -c < 'ccincl_s.l'`"
  545. then
  546.     echo shar: "error transmitting 'ccincl_s.l'" '(should have been 240 characters)'
  547. fi
  548. fi
  549. echo shar: "extracting 'gsrc.c'" '(807 characters)'
  550. if test -f 'gsrc.c'
  551. then
  552.     echo shar: "will not over-write existing file 'gsrc.c'"
  553. else
  554. sed 's/^X//' << \SHAR_EOF > 'gsrc.c'
  555. X/*
  556. X**    Track down ultimate source files.
  557. X*/
  558. X
  559. X#include    <stdio.h>
  560. X#include    <sys/types.h>
  561. X#include    <sys/stat.h>
  562. X#include    "std.h"
  563. X
  564. Xmain(argc, argv)
  565. Xint    argc;
  566. Xchar    **argv;
  567. X{
  568. X    char        buf[80];
  569. X    struct    stat    statbuf;
  570. X    reg    int    i, j;
  571. X    reg    int    lastsuf, firstfile;
  572. X    reg    bool    found;
  573. X
  574. X    lastsuf = 0;
  575. X    firstfile = argc;
  576. X    for (i = 1; i < argc; i++)
  577. X    {
  578. X        if (argv[i][0] == '.')
  579. X            lastsuf = i;
  580. X        or (firstfile == argc)
  581. X            firstfile = i;
  582. X    }
  583. X
  584. X    if (lastsuf > firstfile)
  585. X    {
  586. X        fprintf(stderr, "gsrc: mixed suffixes and filenames\n");
  587. X        exit(1);
  588. X    }
  589. X
  590. X    for (i = firstfile; i < argc; i++)
  591. X    {
  592. X        found = FALSE;
  593. X        for (j = lastsuf; j > 0; j--)
  594. X        {
  595. X            sprintf(buf, "%s%s", argv[i], argv[j]);
  596. X            if (stat(buf, &statbuf) == 0)
  597. X            {
  598. X                if (! found)
  599. X                    found = TRUE;
  600. X                else
  601. X                    printf("%s%s\n", argv[i], argv[j]);
  602. X            }
  603. X        }
  604. X    }
  605. X
  606. X    exit(0);
  607. X}
  608. SHAR_EOF
  609. if test 807 -ne "`wc -c < 'gsrc.c'`"
  610. then
  611.     echo shar: "error transmitting 'gsrc.c'" '(should have been 807 characters)'
  612. fi
  613. fi
  614. echo shar: "extracting 'later.c'" '(1244 characters)'
  615. if test -f 'later.c'
  616. then
  617.     echo shar: "will not over-write existing file 'later.c'"
  618. else
  619. sed 's/^X//' << \SHAR_EOF > 'later.c'
  620. X/*
  621. X**    Find out which arg files are later than a reference file.
  622. X*/
  623. X
  624. Xstatic    char
  625. Xrcs_id[] = "$Header$";
  626. X
  627. X#include    <stdio.h>
  628. X#include    <sys/types.h>
  629. X#include    <sys/stat.h>
  630. X#include    "std.h"
  631. X
  632. Xtypedef    struct    stat    Stat;
  633. X
  634. Xchar    scratchbuf[128];
  635. X
  636. Xmain(argc, argv)
  637. Xint    argc;
  638. Xchar    **argv;
  639. X{
  640. X    Stat        statbuf;
  641. X    reg    time_t    reftime;
  642. X    reg    int    i, n;
  643. X    reg    bool    count  = FALSE;
  644. X    reg    bool    silent = FALSE;
  645. X
  646. X    while (argc > 1 && argv[1][0] == '-')
  647. X    {
  648. X        for (i = 1; argv[1][i] != '\0'; i++)
  649. X        {
  650. X            switch (argv[1][i])
  651. X            {
  652. X
  653. X        when 'c':    count = TRUE;
  654. X
  655. X        when 's':    silent = TRUE;
  656. X
  657. X        otherwise:    usage();
  658. X
  659. X            }
  660. X        }
  661. X
  662. X        argc--;
  663. X        argv++;
  664. X    }
  665. X
  666. X    if (argc < 3)
  667. X        usage();
  668. X    
  669. X    if (stat(argv[1], &statbuf) != 0)
  670. X    {
  671. X        sprintf(scratchbuf, "later, stat %s", argv[1]);
  672. X        perror(scratchbuf);
  673. X        exit(127);
  674. X    }
  675. X
  676. X    argv++;
  677. X    argc--;
  678. X    reftime = statbuf.st_mtime;
  679. X    n = 0;
  680. X
  681. X    while (argc > 1)
  682. X    {
  683. X        if (stat(argv[1], &statbuf) != 0)
  684. X        {
  685. X            sprintf(scratchbuf, "later, stat %s", argv[1]);
  686. X            perror(scratchbuf);
  687. X            exit(127);
  688. X        }
  689. X
  690. X        if (statbuf.st_mtime > reftime)
  691. X        {
  692. X            n++;
  693. X            if (! silent)
  694. X                printf("%s\n", argv[1]);
  695. X        }
  696. X
  697. X        argc--;
  698. X        argv++;
  699. X    }
  700. X
  701. X    exit(count? n: 0);
  702. X}
  703. X
  704. X/*
  705. X**    Tell the unfortunate user how to use later.
  706. X*/
  707. X
  708. Xusage()
  709. X{
  710. X    printf("Usage: later [-cs] reffile file ...\n");
  711. X    exit(1);
  712. X}
  713. SHAR_EOF
  714. if test 1244 -ne "`wc -c < 'later.c'`"
  715. then
  716.     echo shar: "error transmitting 'later.c'" '(should have been 1244 characters)'
  717. fi
  718. fi
  719. echo shar: "extracting 'need.c'" '(996 characters)'
  720. if test -f 'need.c'
  721. then
  722.     echo shar: "will not over-write existing file 'need.c'"
  723. else
  724. sed 's/^X//' << \SHAR_EOF > 'need.c'
  725. X/*
  726. X**    need: a simple utility for text processing with cake
  727. X*/
  728. X
  729. X#include    <stdio.h>
  730. X#include    "std.h"
  731. X
  732. X#define    MAXLINE    256
  733. X
  734. Xmain(argc, argv)
  735. Xint    argc;
  736. Xchar    **argv;
  737. X{
  738. X    reg    FILE    *fp;
  739. X    char        line[MAXLINE];
  740. X
  741. X    if (argc != 2 && argc != 3)
  742. X    {
  743. X        printf("Usage: need program [file]\n");
  744. X        exit(127);
  745. X    }
  746. X
  747. X    if (argc == 2)
  748. X        fp = stdin;
  749. X    else
  750. X    {
  751. X        if ((fp = fopen(argv[2], "r")) == NULL)
  752. X        {
  753. X            printf("need: cannot open %s\n", argv[2]);
  754. X            exit(127);
  755. X        }
  756. X    }
  757. X
  758. X    while (getline(fp, line, MAXLINE) > 0)
  759. X        if (match(line, "NEED"))
  760. X            exit(match(line, argv[1])? 0: 1);
  761. X    
  762. X    exit(127);
  763. X}
  764. X
  765. Xint
  766. Xgetline(fp, s, lim)
  767. Xreg    FILE    *fp;
  768. Xchar        s[];
  769. Xreg    int    lim;
  770. X{
  771. X    reg    int    c, i;
  772. X
  773. X    i = 0;
  774. X    while (--lim > 0 && (c = getc(fp)) != EOF && c != '\n')
  775. X        s[i++] = c;
  776. X
  777. X    if (c == '\n')
  778. X        s[i++] = c;
  779. X
  780. X    s[i] = '\0';
  781. X    return i;
  782. X}
  783. X
  784. Xint
  785. Xmatch(s, t)
  786. Xreg    char    *s;
  787. Xreg    char    *t;
  788. X{
  789. X    reg    int    i, j;
  790. X
  791. X    for (; *s != '\0'; s++)
  792. X    {
  793. X        for (i = 0, j = 0; t[j] != '\0' && s[i] == t[j]; i++, j++)
  794. X            ;
  795. X        if (t[j] == '\0')
  796. X            return TRUE;
  797. X    }
  798. X
  799. X    return FALSE;
  800. X}
  801. SHAR_EOF
  802. if test 996 -ne "`wc -c < 'need.c'`"
  803. then
  804.     echo shar: "error transmitting 'need.c'" '(should have been 996 characters)'
  805. fi
  806. fi
  807. echo shar: "extracting 'needed.c'" '(1001 characters)'
  808. if test -f 'needed.c'
  809. then
  810.     echo shar: "will not over-write existing file 'needed.c'"
  811. else
  812. sed 's/^X//' << \SHAR_EOF > 'needed.c'
  813. X/*
  814. X**    needed: an even simpler utility for text processing with cake
  815. X*/
  816. X
  817. X#include    <stdio.h>
  818. X#include    "std.h"
  819. X
  820. X#define    MAXLINE    256
  821. X
  822. Xmain(argc, argv)
  823. Xint    argc;
  824. Xchar    **argv;
  825. X{
  826. X    extern    char    *match();
  827. X    reg    FILE    *fp;
  828. X    reg    char    *rest;
  829. X    char        line[MAXLINE];
  830. X
  831. X    if (argc != 2)
  832. X    {
  833. X        printf("Usage: needed file\n");
  834. X        exit(127);
  835. X    }
  836. X
  837. X    if ((fp = fopen(argv[1], "r")) == NULL)
  838. X    {
  839. X        printf("needed: cannot open %s\n", argv[1]);
  840. X        exit(127);
  841. X    }
  842. X
  843. X    while (getline(fp, line, MAXLINE) > 0)
  844. X        if ((rest = match(line, "NEED")) != NULL)
  845. X        {
  846. X            printf("%s", rest);
  847. X            exit(0);
  848. X        }
  849. X
  850. X    exit(0);
  851. X}
  852. X
  853. Xint
  854. Xgetline(fp, s, lim)
  855. Xreg    FILE    *fp;
  856. Xchar        s[];
  857. Xreg    int    lim;
  858. X{
  859. X    reg    int    c, i;
  860. X
  861. X    i = 0;
  862. X    while (--lim > 0 && (c = getc(fp)) != EOF && c != '\n')
  863. X        s[i++] = c;
  864. X
  865. X    if (c == '\n')
  866. X        s[i++] = c;
  867. X
  868. X    s[i] = '\0';
  869. X    return i;
  870. X}
  871. X
  872. Xchar *
  873. Xmatch(s, t)
  874. Xreg    char    *s;
  875. Xreg    char    *t;
  876. X{
  877. X    reg    int    i, j;
  878. X
  879. X    for (; *s != '\0'; s++)
  880. X    {
  881. X        for (i = 0, j = 0; t[j] != '\0' && s[i] == t[j]; i++, j++)
  882. X            ;
  883. X
  884. X        if (t[j] == '\0')
  885. X            return s+j;
  886. X    }
  887. X
  888. X    return NULL;
  889. X}
  890. SHAR_EOF
  891. if test 1001 -ne "`wc -c < 'needed.c'`"
  892. then
  893.     echo shar: "error transmitting 'needed.c'" '(should have been 1001 characters)'
  894. fi
  895. fi
  896. echo shar: "extracting 'pattern_s.l'" '(389 characters)'
  897. if test -f 'pattern_s.l'
  898. then
  899.     echo shar: "will not over-write existing file 'pattern_s.l'"
  900. else
  901. sed 's/^X//' << \SHAR_EOF > 'pattern_s.l'
  902. X%{
  903. X/*
  904. X**    Scanner for base
  905. X*/
  906. X
  907. X#include    "std.h"
  908. X
  909. Xextern    int    more;
  910. X%}
  911. X
  912. X%%
  913. X
  914. X"$"            {    return 1;    }
  915. X"[\."            {    return 2;    }
  916. X".\]"            {    return -2;    }
  917. X"\\f(as"        {    return 3;    }
  918. X"\\f(CW"        {    return 3;    }
  919. X"\\fP"            {    return -3;    }
  920. X"\\fR"            {    return -3;    }
  921. X".(p"            {    return 3;    }
  922. X".)p"            {    return -3;    }
  923. X".PS"            {    return 4;    }
  924. X".PE"            {    return -4;    }
  925. X.|\n            {    return 0;    }
  926. X
  927. X%%
  928. X
  929. Xyywrap()
  930. X{
  931. X    more = FALSE;
  932. X    return 1;
  933. X}
  934. SHAR_EOF
  935. if test 389 -ne "`wc -c < 'pattern_s.l'`"
  936. then
  937.     echo shar: "error transmitting 'pattern_s.l'" '(should have been 389 characters)'
  938. fi
  939. fi
  940. echo shar: "extracting 'refs.c'" '(828 characters)'
  941. if test -f 'refs.c'
  942. then
  943.     echo shar: "will not over-write existing file 'refs.c'"
  944. else
  945. sed 's/^X//' << \SHAR_EOF > 'refs.c'
  946. X/*
  947. X**    A program to filter out references.
  948. X*/
  949. X
  950. X#include    <stdio.h>
  951. X#include    "std.h"
  952. X
  953. Xint    more = TRUE;
  954. X
  955. Xmain()
  956. X{
  957. X    extern    char    yytext[];
  958. X    reg    FILE    *out;
  959. X    reg    int    code;
  960. X    reg    bool    init, ignore;
  961. X
  962. X    out = popen("sed -e 's/[     ]*$//'", "w");
  963. X
  964. X    code = yylex();
  965. X    while (more)
  966. X    {
  967. X        if (code == 2)
  968. X        {
  969. X            ignore = FALSE;
  970. X            init = TRUE;
  971. X            code = yylex();
  972. X            while (more && code != -2)
  973. X            {
  974. X                if (streq(yytext, "{"))
  975. X                    ignore = TRUE;
  976. X                or (streq(yytext, "}"))
  977. X                    ignore = FALSE;
  978. X                or (ignore)
  979. X                    ;
  980. X                or (streq(yytext, ","))
  981. X                {
  982. X                    putc('\n', out);
  983. X                    init = TRUE;
  984. X                }
  985. X                or (streq(yytext, " "))
  986. X                {
  987. X                    if (! init)
  988. X                        putc(' ', out);
  989. X                }
  990. X                else
  991. X                {
  992. X                    fprintf(out, "%s", yytext);
  993. X                    init = FALSE;
  994. X                }
  995. X
  996. X                code = yylex();
  997. X            }
  998. X
  999. X            putc('\n', out);
  1000. X        }
  1001. X
  1002. X        code = yylex();
  1003. X    }
  1004. X
  1005. X    pclose(out);
  1006. X    exit(0);
  1007. X}
  1008. SHAR_EOF
  1009. if test 828 -ne "`wc -c < 'refs.c'`"
  1010. then
  1011.     echo shar: "error transmitting 'refs.c'" '(should have been 828 characters)'
  1012. fi
  1013. fi
  1014. echo shar: "extracting 'std.h'" '(1030 characters)'
  1015. if test -f 'std.h'
  1016. then
  1017.     echo shar: "will not over-write existing file 'std.h'"
  1018. else
  1019. sed 's/^X//' << \SHAR_EOF > 'std.h'
  1020. X/*
  1021. X**    Standard definitions for C
  1022. X**
  1023. X**    $Header: /mip/zs/src/sys/cake/RCS/std.h,v 1.13 86/06/15 18:36:30 zs Exp $
  1024. X*/
  1025. X
  1026. X#define    or        else if
  1027. X#define    when        break;case
  1028. X#define    otherwise    break;default
  1029. X#define    loop        for(;;)
  1030. X#define    until(expr)    while(!(expr))
  1031. X#ifndef    reg
  1032. X#define    reg        register
  1033. X#endif
  1034. X#ifndef    bool
  1035. X#define    bool        char
  1036. X#endif
  1037. X
  1038. X#define    uint        unsigned int
  1039. X#define    ushort        unsigned short
  1040. X#define    uchar        unsigned char
  1041. X
  1042. X#define    max(a, b)    ((a) > (b) ? (a) : (b))
  1043. X#define    min(a, b)    ((a) < (b) ? (a) : (b))
  1044. X
  1045. X#define streq(s1, s2)        (strcmp(s1, s2) == 0)
  1046. X#define strdiff(s1, s2)        (strcmp(s1, s2) != 0)
  1047. X#define strneq(s1, s2, n)    (strncmp(s1, s2, n) == 0)
  1048. X#define strndiff(s1, s2, n)    (strncmp(s1, s2, n) != 0)
  1049. X
  1050. X#define    ungetchar(c)        ungetc(c, stdin)
  1051. X#define make(type)        ((type *) newmem(sizeof(type)))
  1052. X#define make_many(type, count)    ((type *) newmem(count * sizeof(type)))
  1053. X
  1054. X#ifndef    TRUE
  1055. X#define    TRUE        1
  1056. X#endif
  1057. X#ifndef    FALSE
  1058. X#define    FALSE        0
  1059. X#endif
  1060. X#ifndef    NULL
  1061. X#define    NULL        0
  1062. X#endif
  1063. X
  1064. X#define    CNULL        (char *) 0
  1065. X#define    LNULL        (List *) 0
  1066. SHAR_EOF
  1067. if test 1030 -ne "`wc -c < 'std.h'`"
  1068. then
  1069.     echo shar: "error transmitting 'std.h'" '(should have been 1030 characters)'
  1070. fi
  1071. fi
  1072. echo shar: "extracting 'sub.c'" '(4337 characters)'
  1073. if test -f 'sub.c'
  1074. then
  1075.     echo shar: "will not over-write existing file 'sub.c'"
  1076. else
  1077. sed 's/^X//' << \SHAR_EOF > 'sub.c'
  1078. X/*
  1079. X**    Sub - do substitutions on arguments
  1080. X*/
  1081. X
  1082. Xstatic    char
  1083. Xrcs_id[] = "$Header$";
  1084. X
  1085. X#include    "std.h"
  1086. X#include    <ctype.h>
  1087. X
  1088. Xchar    var_char = 'X';
  1089. X
  1090. Xmain(argc, argv)
  1091. Xint    argc;
  1092. Xchar    **argv;
  1093. X{
  1094. X    extern    bool    match();
  1095. X    extern    char    *ground();
  1096. X    reg    char    *old, *new;
  1097. X    reg    bool    ignore;
  1098. X    reg    int    unmatched, i;
  1099. X    reg    char    *sep;
  1100. X
  1101. X    ignore = FALSE;
  1102. X    unmatched = 0;
  1103. X    while (argc > 1 && argv[1][0] == '-')
  1104. X    {
  1105. X        for (i = 1; argv[1][i] != '\0'; i++)
  1106. X        {
  1107. X            switch (argv[1][i])
  1108. X            {
  1109. X
  1110. X        when 'i':
  1111. X                ignore = TRUE;
  1112. X        when 'v':
  1113. X                if (argv[1][i+2] != '\0')
  1114. X                    usage();
  1115. X
  1116. X                var_char = argv[1][i+1];
  1117. X                goto nextword;
  1118. X        otherwise:
  1119. X                usage();
  1120. X            }
  1121. X        }
  1122. X
  1123. Xnextword:
  1124. X        argc--;
  1125. X        argv++;
  1126. X    }
  1127. X
  1128. X    if (argc < 2)
  1129. X        usage();
  1130. X    
  1131. X    old = argv[1];
  1132. X    new = argv[2];
  1133. X    argv += 2;
  1134. X    argc -= 2;
  1135. X
  1136. X    sep = "";
  1137. X    while (argc > 1)
  1138. X    {
  1139. X        if (! match(argv[1], old))
  1140. X            unmatched++;
  1141. X        else
  1142. X        {
  1143. X            printf("%s%s", sep, ground(new));
  1144. X            sep = " ";
  1145. X        }
  1146. X
  1147. X        argc--;
  1148. X        argv++;
  1149. X    }
  1150. X
  1151. X    printf("\n");
  1152. X    exit(ignore? 0: unmatched);
  1153. X}
  1154. X
  1155. X/*
  1156. X**    Tell the unfortunate user how to use sub.
  1157. X*/
  1158. X
  1159. Xusage()
  1160. X{
  1161. X    printf("Usage: sub [-i] [-vX] oldpattern newpattern name ...\n");
  1162. X    exit(1);
  1163. X}
  1164. X
  1165. X/*
  1166. X**    Module to manipulate Cake patterns.
  1167. X*/
  1168. X
  1169. Xtypedef    struct    s_env
  1170. X{
  1171. X    char    *en_val;
  1172. X    bool    en_bound;
  1173. X} Env;
  1174. X
  1175. X#define    NOVAR     10
  1176. X#define    MAXVAR     11
  1177. X#define    MAXSIZE    128
  1178. X
  1179. XEnv    env[MAXVAR];
  1180. X
  1181. X/*
  1182. X**    This function initialises the environment of domatch.
  1183. X*/
  1184. X
  1185. Xbool
  1186. Xmatch(str, pat)
  1187. Xreg    char    *str;
  1188. Xreg    char    *pat;
  1189. X{
  1190. X    extern    bool    domatch();
  1191. X    reg    int    i;
  1192. X    reg    char    *s, *p;
  1193. X
  1194. X    p = pat+strlen(pat)-1;
  1195. X    if (*p != var_char && !isdigit(*p))    /* not part of a var */
  1196. X    {
  1197. X        s = str+strlen(str)-1;
  1198. X        if (*s != *p)            /* last chars differ */
  1199. X            return FALSE;
  1200. X    }
  1201. X
  1202. X    for (i = 0; i < MAXVAR; i++)
  1203. X        env[i].en_bound = FALSE;
  1204. X
  1205. X    return domatch(str, pat);
  1206. X}
  1207. X
  1208. X/*
  1209. X**    Match a string against a pattern.
  1210. X**    The pattern is expected to have been dereferenced.
  1211. X**    To handle nondeterminism, a brute force recursion approach
  1212. X**    is taken.
  1213. X*/
  1214. X
  1215. Xbool
  1216. Xdomatch(str, patstr)
  1217. Xreg    char    *str;
  1218. Xreg    char    *patstr;
  1219. X{
  1220. X    extern    char    *new_name();
  1221. X    char        buf[MAXSIZE];
  1222. X    reg    char    *follow;
  1223. X    reg    char    *s, *t;
  1224. X    reg    int    varno;
  1225. X    reg    int    i;
  1226. X    reg    bool    more;
  1227. X
  1228. X    if (patstr[0] == var_char)
  1229. X    {
  1230. X        if (isdigit(patstr[1]))
  1231. X        {
  1232. X            varno  = patstr[1] - '0';
  1233. X            follow = patstr + 2;
  1234. X        }
  1235. X        else
  1236. X        {
  1237. X            varno  = NOVAR;
  1238. X            follow = patstr + 1;
  1239. X        }
  1240. X
  1241. X        if (env[varno].en_bound)
  1242. X        {
  1243. X            /* lifetime of buf is local */
  1244. X            strcpy(buf, env[varno].en_val);
  1245. X            strcat(buf, follow);
  1246. X            return domatch(str, buf);
  1247. X        }
  1248. X
  1249. X        i = 0;
  1250. X        buf[0] = '\0';
  1251. X        env[varno].en_bound = TRUE;
  1252. X        env[varno].en_val = buf;
  1253. X
  1254. X        /* keep invariant: buf = tentative value of var  */
  1255. X        /* must consider *s == \0, but do not overshoot  */
  1256. X        for (s = str, more = TRUE; more; s++)
  1257. X        {
  1258. X            if (domatch(s, follow))
  1259. X            {
  1260. X                /* lifetime of buf is now global */
  1261. X                env[varno].en_val = new_name(buf);
  1262. X                return TRUE;
  1263. X            }
  1264. X
  1265. X            /* maintain invariant */
  1266. X            buf[i++] = *s;
  1267. X            buf[i]   = '\0';
  1268. X
  1269. X            more = (*s != '\0');
  1270. X        }
  1271. X        
  1272. X        /* no luck, match failed */
  1273. X        env[varno].en_bound = FALSE;
  1274. X        return FALSE;
  1275. X    }
  1276. X
  1277. X    /* here we have something other than a variable first off */
  1278. X    for (s = str, t = patstr; *t != '\0' && *t != var_char; s++, t++)
  1279. X    {
  1280. X        if (*t == '\\')
  1281. X            t++;    /* the new *t is not checked for % */
  1282. X        
  1283. X        if (*s != *t)
  1284. X            return FALSE;
  1285. X    }
  1286. X
  1287. X    /* see if we have come to the end of the pattern */
  1288. X    if (*t == '\0')
  1289. X        return *s == '\0';
  1290. X    
  1291. X    /* if not, recurse on the next variable */
  1292. X    return domatch(s, t);
  1293. X}
  1294. X
  1295. X/*
  1296. X**    Ground the argument string, i.e. replace all occurrences
  1297. X**    of variables in it. It is fatal error for the string to
  1298. X**    contain a variable which has no value.
  1299. X*/
  1300. X
  1301. Xchar *
  1302. Xground(str)
  1303. Xreg    char    *str;
  1304. X{
  1305. X    extern    char    *new_name();
  1306. X    reg    char    *s, *t;
  1307. X    reg    int    i, var;
  1308. X    char        buf[MAXSIZE];
  1309. X
  1310. X    i = 0;
  1311. X    for (s = str; *s != '\0'; s++)
  1312. X    {
  1313. X        if (*s == var_char)
  1314. X        {
  1315. X            if (isdigit(s[1]))
  1316. X                var = *++s - '0';
  1317. X            else
  1318. X                var = NOVAR;
  1319. X            
  1320. X            if (! env[var].en_bound)
  1321. X            {
  1322. X                printf("Attempt to use undefined value in %s\n", str);
  1323. X                exit(1);
  1324. X            }
  1325. X
  1326. X            for (t = env[var].en_val; *t != '\0'; t++)
  1327. X                buf[i++] = *t;
  1328. X        }
  1329. X        or (*s == '\\')
  1330. X        {
  1331. X            if (s[1] != '\0')
  1332. X                buf[i++] = *++s;
  1333. X        }
  1334. X        else
  1335. X            buf[i++] = *s;
  1336. X    }
  1337. X
  1338. X    if (i >= MAXSIZE)
  1339. X    {
  1340. X        printf("Ran out of buffer\n");
  1341. X        exit(1);
  1342. X    }
  1343. X
  1344. X    buf[i] = '\0';
  1345. X    return new_name(buf);
  1346. X}
  1347. X
  1348. Xchar *
  1349. Xnew_name(str)
  1350. Xreg    char    *str;
  1351. X{
  1352. X    extern    char    *malloc();
  1353. X    reg    char    *copy;
  1354. X
  1355. X    copy = malloc(strlen(str) + 1);
  1356. X    strcpy(copy, str);
  1357. X    return copy;
  1358. X}
  1359. SHAR_EOF
  1360. if test 4337 -ne "`wc -c < 'sub.c'`"
  1361. then
  1362.     echo shar: "error transmitting 'sub.c'" '(should have been 4337 characters)'
  1363. fi
  1364. fi
  1365. echo shar: "extracting 'subcmd.c'" '(5233 characters)'
  1366. if test -f 'subcmd.c'
  1367. then
  1368.     echo shar: "will not over-write existing file 'subcmd.c'"
  1369. else
  1370. sed 's/^X//' << \SHAR_EOF > 'subcmd.c'
  1371. X/*
  1372. X**    Subcmd - execute commands with arguments based on substitutions
  1373. X*/
  1374. X
  1375. Xstatic    char
  1376. Xrcs_id[] = "$Header$";
  1377. X
  1378. X#include    <stdio.h>
  1379. X#include    <ctype.h>
  1380. X#include    "std.h"
  1381. X
  1382. X#define    MAXLEN    1024
  1383. X
  1384. Xchar    var_char = 'X';
  1385. X
  1386. Xmain(argc, argv)
  1387. Xint    argc;
  1388. Xchar    **argv;
  1389. X{
  1390. X    extern    bool    match();
  1391. X    extern    char    *ground();
  1392. X    reg    char    *cmd, *old, *new;
  1393. X    reg    int    unmatched, i;
  1394. X    reg    bool    fast, general, ignore, noexec, needzero;
  1395. X    reg    FILE    *csh;
  1396. X    char        buf[MAXLEN];
  1397. X
  1398. X    fast     = FALSE;
  1399. X    general  = FALSE;
  1400. X    ignore   = FALSE;
  1401. X    noexec   = FALSE;
  1402. X    needzero = TRUE;
  1403. X    unmatched = 0;
  1404. X    while (argc > 1 && argv[1][0] == '-')
  1405. X    {
  1406. X        for (i = 1; argv[1][i] != '\0'; i++)
  1407. X        {
  1408. X            switch (argv[1][i])
  1409. X            {
  1410. X
  1411. X        when 'f':    fast = TRUE;
  1412. X
  1413. X        when 'g':    general = TRUE;
  1414. X
  1415. X        when 'i':    ignore = TRUE;
  1416. X
  1417. X        when 'n':    noexec = TRUE;
  1418. X
  1419. X        when 'v':    if (i != 1)
  1420. X                    usage();
  1421. X
  1422. X                var_char = argv[1][2];
  1423. X                goto nextword;
  1424. X
  1425. X        when 'z':    needzero = FALSE;
  1426. X
  1427. X        otherwise:    usage();
  1428. X
  1429. X            }
  1430. X        }
  1431. X
  1432. Xnextword:
  1433. X        argc--;
  1434. X        argv++;
  1435. X    }
  1436. X
  1437. X    if (argc < 3)
  1438. X        usage();
  1439. X    
  1440. X    cmd = argv[1];
  1441. X    old = argv[2];
  1442. X    new = argv[3];
  1443. X    argv += 3;
  1444. X    argc -= 3;
  1445. X
  1446. X    if (fast)
  1447. X    {
  1448. X        csh = popen("/bin/csh -fs", "w");
  1449. X        if (csh == (FILE *) NULL)
  1450. X        {
  1451. X            printf("subcmd: cannot popen csh\n");
  1452. X            exit(1);
  1453. X        }
  1454. X    }
  1455. X
  1456. X    while (argc > 1)
  1457. X    {
  1458. X        if (! match(argv[1], old))
  1459. X            unmatched++;
  1460. X        else
  1461. X        {
  1462. X            if (general)
  1463. X                sprintf(buf, cmd, argv[1], ground(new));
  1464. X            else
  1465. X                sprintf(buf, "%s %s %s", cmd, argv[1], ground(new));
  1466. X
  1467. X            if (strlen(buf) >= MAXLEN)
  1468. X                printf("subcmd: command too long\n");
  1469. X            or (noexec)
  1470. X                printf("would be executing %s\n", buf);
  1471. X            or (fast)
  1472. X            {
  1473. X                printf("executing %s\n", buf);
  1474. X                fprintf(csh, "%s\n", buf);
  1475. X            }
  1476. X            else
  1477. X            {
  1478. X                printf("executing %s\n", buf);
  1479. X                if (system(buf) != 0 && needzero)
  1480. X                    printf("subcmd: command failed\n");
  1481. X            }
  1482. X        }
  1483. X
  1484. X        argv++;
  1485. X        argc--;
  1486. X    }
  1487. X
  1488. X    if (fast)
  1489. X        pclose(csh);
  1490. X
  1491. X    exit(ignore? 0: unmatched);
  1492. X}
  1493. X
  1494. X/*
  1495. X**    Tell the unfortunate user how to use subcmd.
  1496. X*/
  1497. X
  1498. Xusage()
  1499. X{
  1500. X    printf("Usage: subcmd [-fginz] [-vX] cmd oldpattern newpattern files ...\n");
  1501. X    exit(1);
  1502. X}
  1503. X
  1504. X/*
  1505. X**    Module to manipulate Cake patterns.
  1506. X*/
  1507. X
  1508. Xtypedef    struct    s_env
  1509. X{
  1510. X    char    *en_val;
  1511. X    bool    en_bound;
  1512. X} Env;
  1513. X
  1514. X#define    NOVAR     10
  1515. X#define    MAXVAR     11
  1516. X#define    MAXSIZE    128
  1517. X
  1518. XEnv    env[MAXVAR];
  1519. X
  1520. X/*
  1521. X**    This function initialises the environment of domatch.
  1522. X*/
  1523. X
  1524. Xbool
  1525. Xmatch(str, pat)
  1526. Xreg    char    *str;
  1527. Xreg    char    *pat;
  1528. X{
  1529. X    extern    bool    domatch();
  1530. X    reg    int    i;
  1531. X    reg    char    *s, *p;
  1532. X
  1533. X    p = pat+strlen(pat)-1;
  1534. X    if (*p != var_char && !isdigit(*p))    /* not part of a var */
  1535. X    {
  1536. X        s = str+strlen(str)-1;
  1537. X        if (*s != *p)            /* last chars differ */
  1538. X            return FALSE;
  1539. X    }
  1540. X
  1541. X    for (i = 0; i < MAXVAR; i++)
  1542. X        env[i].en_bound = FALSE;
  1543. X
  1544. X    return domatch(str, pat);
  1545. X}
  1546. X
  1547. X/*
  1548. X**    Match a string against a pattern.
  1549. X**    The pattern is expected to have been dereferenced.
  1550. X**    To handle nondeterminism, a brute force recursion approach
  1551. X**    is taken.
  1552. X*/
  1553. X
  1554. Xbool
  1555. Xdomatch(str, patstr)
  1556. Xreg    char    *str;
  1557. Xreg    char    *patstr;
  1558. X{
  1559. X    extern    char    *new_name();
  1560. X    char        buf[MAXSIZE];
  1561. X    reg    char    *follow;
  1562. X    reg    char    *s, *t;
  1563. X    reg    int    varno;
  1564. X    reg    int    i;
  1565. X    reg    bool    more;
  1566. X
  1567. X    if (patstr[0] == var_char)
  1568. X    {
  1569. X        if (isdigit(patstr[1]))
  1570. X        {
  1571. X            varno  = patstr[1] - '0';
  1572. X            follow = patstr + 2;
  1573. X        }
  1574. X        else
  1575. X        {
  1576. X            varno  = NOVAR;
  1577. X            follow = patstr + 1;
  1578. X        }
  1579. X
  1580. X        if (env[varno].en_bound)
  1581. X        {
  1582. X            /* lifetime of buf is local */
  1583. X            strcpy(buf, env[varno].en_val);
  1584. X            strcat(buf, follow);
  1585. X            return domatch(str, buf);
  1586. X        }
  1587. X
  1588. X        i = 0;
  1589. X        buf[0] = '\0';
  1590. X        env[varno].en_bound = TRUE;
  1591. X        env[varno].en_val = buf;
  1592. X
  1593. X        /* keep invariant: buf = tentative value of var  */
  1594. X        /* must consider *s == \0, but do not overshoot  */
  1595. X        for (s = str, more = TRUE; more; s++)
  1596. X        {
  1597. X            if (domatch(s, follow))
  1598. X            {
  1599. X                /* lifetime of buf is now global */
  1600. X                env[varno].en_val = new_name(buf);
  1601. X                return TRUE;
  1602. X            }
  1603. X
  1604. X            /* maintain invariant */
  1605. X            buf[i++] = *s;
  1606. X            buf[i]   = '\0';
  1607. X
  1608. X            more = (*s != '\0');
  1609. X        }
  1610. X        
  1611. X        /* no luck, match failed */
  1612. X        env[varno].en_bound = FALSE;
  1613. X        return FALSE;
  1614. X    }
  1615. X
  1616. X    /* here we have something other than a variable first off */
  1617. X    for (s = str, t = patstr; *t != '\0' && *t != var_char; s++, t++)
  1618. X    {
  1619. X        if (*t == '\\')
  1620. X            t++;    /* the new *t is not checked for % */
  1621. X        
  1622. X        if (*s != *t)
  1623. X            return FALSE;
  1624. X    }
  1625. X
  1626. X    /* see if we have come to the end of the pattern */
  1627. X    if (*t == '\0')
  1628. X        return *s == '\0';
  1629. X    
  1630. X    /* if not, recurse on the next variable */
  1631. X    return domatch(s, t);
  1632. X}
  1633. X
  1634. X/*
  1635. X**    Ground the argument string, i.e. replace all occurrences
  1636. X**    of variables in it. It is fatal error for the string to
  1637. X**    contain a variable which has no value.
  1638. X*/
  1639. X
  1640. Xchar *
  1641. Xground(str)
  1642. Xreg    char    *str;
  1643. X{
  1644. X    extern    char    *new_name();
  1645. X    reg    char    *s, *t;
  1646. X    reg    int    i, var;
  1647. X    char        buf[MAXSIZE];
  1648. X
  1649. X    i = 0;
  1650. X    for (s = str; *s != '\0'; s++)
  1651. X    {
  1652. X        if (*s == var_char)
  1653. X        {
  1654. X            if (isdigit(s[1]))
  1655. X                var = *++s - '0';
  1656. X            else
  1657. X                var = NOVAR;
  1658. X            
  1659. X            if (! env[var].en_bound)
  1660. X            {
  1661. X                printf("Attempt to use undefined value in %s\n", str);
  1662. X                exit(1);
  1663. X            }
  1664. X
  1665. X            for (t = env[var].en_val; *t != '\0'; t++)
  1666. X                buf[i++] = *t;
  1667. X        }
  1668. X        or (*s == '\\')
  1669. X        {
  1670. X            if (s[1] != '\0')
  1671. X                buf[i++] = *++s;
  1672. X        }
  1673. X        else
  1674. X            buf[i++] = *s;
  1675. X    }
  1676. X
  1677. X    if (i >= MAXSIZE)
  1678. X    {
  1679. X        printf("Ran out of buffer\n");
  1680. X        exit(1);
  1681. X    }
  1682. X
  1683. X    buf[i] = '\0';
  1684. X    return new_name(buf);
  1685. X}
  1686. X
  1687. Xchar *
  1688. Xnew_name(str)
  1689. Xreg    char    *str;
  1690. X{
  1691. X    extern    char    *malloc();
  1692. X    reg    char    *copy;
  1693. X
  1694. X    copy = malloc(strlen(str) + 1);
  1695. X    strcpy(copy, str);
  1696. X    return copy;
  1697. X}
  1698. SHAR_EOF
  1699. if test 5233 -ne "`wc -c < 'subcmd.c'`"
  1700. then
  1701.     echo shar: "error transmitting 'subcmd.c'" '(should have been 5233 characters)'
  1702. fi
  1703. fi
  1704. echo shar: "extracting 'usrc.c'" '(904 characters)'
  1705. if test -f 'usrc.c'
  1706. then
  1707.     echo shar: "will not over-write existing file 'usrc.c'"
  1708. else
  1709. sed 's/^X//' << \SHAR_EOF > 'usrc.c'
  1710. X/*
  1711. X**    Track down ultimate source files.
  1712. X*/
  1713. X
  1714. X#include    <stdio.h>
  1715. X#include    <sys/types.h>
  1716. X#include    <sys/stat.h>
  1717. X#include    "std.h"
  1718. X
  1719. Xmain(argc, argv)
  1720. Xint    argc;
  1721. Xchar    **argv;
  1722. X{
  1723. X    char        buf[80];
  1724. X    struct    stat    statbuf;
  1725. X    reg    int    i, j, errcnt;
  1726. X    reg    int    lastsuf, firstfile;
  1727. X    reg    bool    found;
  1728. X
  1729. X    lastsuf = 0;
  1730. X    firstfile = argc;
  1731. X    for (i = 1; i < argc; i++)
  1732. X    {
  1733. X        if (argv[i][0] == '.')
  1734. X            lastsuf = i;
  1735. X        or (firstfile == argc)
  1736. X            firstfile = i;
  1737. X    }
  1738. X
  1739. X    if (lastsuf > firstfile)
  1740. X    {
  1741. X        fprintf(stderr, "usrc: mixed suffixes and filenames\n");
  1742. X        exit(1);
  1743. X    }
  1744. X
  1745. X    errcnt = 0;
  1746. X    for (i = firstfile; i < argc; i++)
  1747. X    {
  1748. X        found = FALSE;
  1749. X        for (j = lastsuf; j > 0; j--)
  1750. X        {
  1751. X            sprintf(buf, "%s%s", argv[i], argv[j]);
  1752. X            if (stat(buf, &statbuf) == 0)
  1753. X            {
  1754. X                found = TRUE;
  1755. X                printf("%s\n", buf);
  1756. X                break;
  1757. X            }
  1758. X        }
  1759. X
  1760. X        if (! found)
  1761. X        {
  1762. X            fprintf(stderr, "usrc: cannot find source for %s\n", argv[i]);
  1763. X            errcnt++;
  1764. X        }
  1765. X    }
  1766. X
  1767. X    exit(errcnt);
  1768. X}
  1769. SHAR_EOF
  1770. if test 904 -ne "`wc -c < 'usrc.c'`"
  1771. then
  1772.     echo shar: "error transmitting 'usrc.c'" '(should have been 904 characters)'
  1773. fi
  1774. fi
  1775. exit 0
  1776. #    End of shell archive
  1777.